package jee.boot.module.oauth2.rest;

import jee.boot.common.basic.result.ResponseMessage;
import jee.boot.common.basic.result.Result;
import jee.boot.common.utils.DateUtils;
import jee.boot.entity.auth.Account;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.provider.ClientDetails;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationDetails;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Date;

/**
 * OAuth2相关操作
 */
@RestController
@RequestMapping(value = "/oauth")
public class OAuth2Controller {
    private Logger logger= LoggerFactory.getLogger(getClass());
    @Autowired
    private TokenStore tokenStore;
    @Autowired
    private RedisTemplate<String,Object> redisTemplate;
    @Value("${oauth.enableAutoRefreshToken:true}")
    private boolean enableAutoRefreshToken = true;
    @Autowired
    private ClientDetailsService clientDetailsService;
    /**
     * 移除token(登出)
     * 移除access_token和refresh_token
     */
    @PostMapping(value = "/remove/token")
    public ResponseMessage<Object> removeToken() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (authentication != null) {
            if (authentication instanceof OAuth2Authentication) {
                OAuth2AuthenticationDetails details = (OAuth2AuthenticationDetails) authentication.getDetails();
                String access_token = details.getTokenValue();
                OAuth2AccessToken accessToken = tokenStore.readAccessToken(access_token);
                if (accessToken != null) {
                    // 移除access_token
                    tokenStore.removeAccessToken(accessToken);
                    // 移除refresh_token
                    if (accessToken.getRefreshToken() != null) {
                        tokenStore.removeRefreshToken(accessToken.getRefreshToken());
                    }
                }
            }

        }
        return Result.success();
    }
    /**
     * 清除所有redis缓存
     */
    @RequestMapping(value = "/flush/cache")
    public ResponseMessage<Object> flush() {
        redisTemplate.getConnectionFactory().getConnection().flushAll();
        return Result.success();
    }

    /**
     * 刷新token有效时间
     */
    @PostMapping(value = "/refresh/token")
    public ResponseMessage<Account> refresh(@RequestBody Account entity) {
        if (enableAutoRefreshToken) {
            Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
            if (authentication != null) {
                if (authentication instanceof OAuth2Authentication) {
                    OAuth2Authentication auth = (OAuth2Authentication) authentication;
                    OAuth2AccessToken accessToken = tokenStore.getAccessToken(auth);
                    if (accessToken instanceof DefaultOAuth2AccessToken) {
                        DefaultOAuth2AccessToken token = (DefaultOAuth2AccessToken) accessToken;
                        ClientDetails client = clientDetailsService.loadClientByClientId(auth.getOAuth2Request().getClientId());
                        Integer validity = client.getAccessTokenValiditySeconds();
                        Date date=new Date(System.currentTimeMillis() + validity * 1000);
                        token.setExpiration(date);
                        tokenStore.storeAccessToken(token, auth);
                        logger.info("session["+token.getValue()+"]的过期时间延迟至:"+ DateUtils.formatDateTime(date));
                    }
                }
            }
        }
        return Result.success();
    }
}
